﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Thor.Common;
using Thor.Domain;

namespace Thor.Domain.Configuration
{
    /// <summary>
    /// Manages Thor's settings.
    /// </summary>
    public class SettingsManager
    {
        #region Fields

        private ISettingsRepository _settingsRepository = null;
        private Settings _settings = null;

        #endregion

        #region Constructors

        public SettingsManager(ISettingsRepository settingsRepository)
        {
            _settingsRepository = settingsRepository;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Settings for Thor.
        /// </summary>
        public Settings Settings
        {
            get
            {
                if (_settings == null)
                {
                    _settings = _settingsRepository.Fetch();

                    if(_settings != null)
                        _settings.Decrypt();
                }

                return _settings;
            }
            set { _settings = value; }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Saves the settings for Thor.
        /// </summary>
        public void Save()
        {
            if (Settings != null)
            {
                if(!Settings.IsEncrypted)
                    Settings.Encrypt();

                if (_settingsRepository.Fetch() != null)
                    _settingsRepository.Update(Settings);
                else
                    _settingsRepository.Insert(Settings);
            }
        }

        /// <summary>
        /// Gets a concrete implementation of ISettingsRepository.
        /// </summary>
        /// <param name="assemblyPath">Full path to the assembly.</param>
        /// <param name="typeName">Full type name of the type in the assembly that implements ISettingsRepository.</param>
        /// <returns></returns>
        public static ISettingsRepository GetRepository(string assemblyPath, string typeName, Dictionary<string, object> repositoryParameters)
        {
            //Load the assembly from the specified path.
            Assembly assembly = Assembly.LoadFile(assemblyPath);

            //Load the type
            Type type = assembly.GetType(typeName);

            //Get the constructor
            Type[] constructorTypes = new Type[1];
            constructorTypes[0] = typeof(Dictionary<string, object>);
            ConstructorInfo constructorInfo = type.GetConstructor(constructorTypes);

            //Invoke the constructor and return a new instance
            if (constructorInfo != null)
                return constructorInfo.Invoke(new object[]{repositoryParameters}) as ISettingsRepository;

            return null;
        }

        #endregion
    }
}
